// cmd/main.go
package main

import (
	"convert_tunnel_detector/packet"
	"fmt"
	"github.com/google/gopacket/layers"
	"log"
)

func main() {
	//parser, err := packet.NewOSPFParser("ospf.cap")
	parser, err := packet.NewOSPFParser("ospf_link_ack.pcap")
	if err != nil {
		log.Fatal(err)
	}

	pktChan := parser.Start()

	for pkt := range pktChan {
		fmt.Printf("OSPF Packet from %v to %v\n", pkt.SourceIP, pkt.DestIP)
		fmt.Printf("Type: %v\n", pkt.Type)
		fmt.Printf("Router ID: %v\n", pkt.RouterID)

		switch pkt.Type {
		case layers.OSPFHello:
			if pkt.HelloFields != nil {
				fmt.Printf("Hello Packet Details:\n")
				fmt.Printf("  Network Mask: %v\n", pkt.HelloFields.NetworkMask)
				fmt.Printf("  Hello Interval: %d\n", pkt.HelloFields.HelloInterval)
				fmt.Printf("  Options: 0x%02x\n", pkt.HelloFields.Options)
				fmt.Printf("  Priority: %d\n", pkt.HelloFields.Priority)
				fmt.Printf("  Dead Interval: %d\n", pkt.HelloFields.DeadInterval)
				fmt.Printf("  DR: %v\n", pkt.HelloFields.DesignatedRouter)
				fmt.Printf("  BDR: %v\n", pkt.HelloFields.BackupDesignatedRouter)
				fmt.Printf("  Neighbors (%d):\n", len(pkt.HelloFields.Neighbors))
				for i, neighbor := range pkt.HelloFields.Neighbors {
					fmt.Printf("    %d. %v\n", i+1, neighbor)
				}
			}

		case layers.OSPFDatabaseDescription:
			if pkt.DDFields != nil {
				fmt.Printf("DD Packet Details:\n")
				fmt.Printf("  Interface MTU: %d\n", pkt.DDFields.InterfaceMTU)
				fmt.Printf("  Options: 0x%02x\n", pkt.DDFields.Options)
				fmt.Printf("  Flags: 0x%02x (", pkt.DDFields.Flags)
				if pkt.DDFields.IsMaster() {
					fmt.Printf("MASTER ")
				}
				if pkt.DDFields.IsInitialize() {
					fmt.Printf("INIT ")
				}
				if pkt.DDFields.HasMore() {
					fmt.Printf("MORE")
				}
				fmt.Printf(")\n")
				fmt.Printf("  DD Sequence: %d\n", pkt.DDFields.DDSequence)

				fmt.Printf("  LSA Headers (%d):\n", len(pkt.DDFields.LSAHeaders))
				for i, lsa := range pkt.DDFields.LSAHeaders {
					fmt.Printf("    %d. Type=%d, LSID=%v, AdvRouter=%v, Seq=0x%08x\n",
						i+1, lsa.Type, lsa.LSID, lsa.AdvertisingRouter, lsa.SequenceNum)
				}
			}

		case layers.OSPFLinkStateRequest:
			if pkt.LSRFields != nil {
				fmt.Printf("LSR Packet Details:\n")
				fmt.Printf("  Number of LSA Requests: %d\n", len(pkt.LSRFields.LSARequests))
				for i, req := range pkt.LSRFields.LSARequests {
					fmt.Printf("  Request %d:\n", i+1)
					fmt.Printf("    LS Type: %d\n", req.LSType)
					fmt.Printf("    LSID: %v\n", req.LSID)
					fmt.Printf("    Advertising Router: %v\n", req.AdvertisingRouter)
				}
			}

		case layers.OSPFLinkStateUpdate:
			if pkt.LSUFields != nil {
				fmt.Printf("LSU Packet Details:\n")
				fmt.Printf("  Number of LSAs: %d\n", pkt.LSUFields.NumOfLSAs)
				for i, lsa := range pkt.LSUFields.LSAs {
					fmt.Printf("  LSA %d:\n", i+1)
					fmt.Printf("    Header:\n")
					fmt.Printf("      Age: %d\n", lsa.Header.Age)
					fmt.Printf("      Type: %d\n", lsa.Header.Type)
					fmt.Printf("      LSID: %v\n", lsa.Header.LSID)
					fmt.Printf("      Advertising Router: %v\n", lsa.Header.AdvertisingRouter)
					fmt.Printf("      Sequence Number: 0x%08x\n", lsa.Header.SequenceNum)
					fmt.Printf("      Checksum: 0x%04x\n", lsa.Header.Checksum)
					fmt.Printf("      Length: %d\n", lsa.Header.Length)
					fmt.Printf("      Options: 0x%02x\n", lsa.Header.Options)
				}
			}

		case layers.OSPFLinkStateAcknowledgment:
			if pkt.LSAckFields != nil {
				fmt.Printf("LSAck Packet Details:\n")
				fmt.Printf("  Number of LSA Headers: %d\n", len(pkt.LSAckFields.LSAHeaders))
				for i, header := range pkt.LSAckFields.LSAHeaders {
					fmt.Printf("  LSA Header %d:\n", i+1)
					fmt.Printf("    Type=%d, LSID=%v, AdvRouter=%v, Seq=0x%08x\n",
						header.Type, header.LSID, header.AdvertisingRouter, header.SequenceNum)
				}
			}
		}
		fmt.Println("------------------------")
	}
}
